package boardData;
import iodevice.CommandPhalanx;
import iodevice.Kdoparser;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import ChessEngine.AbstractSearch;
import ChessEngine.AlphaBeta;
import ChessEngine.moveGenerator.Exceptions.BoardException;

/**
 * Hauptklasse der Engine
 * 
 * @author Fabian Hewer
 * @Version 0.a.4 (9.8.'11)
 */
public class MainEngine {

	private Board board;
	private LinkedList commandQueue = new LinkedList();
	private static boolean finished = false;
	private AlphaBeta searcher;
	private boolean searching = false;
	
	public static void main (String[] args) throws Throwable {
		try {
		MainEngine e = new MainEngine();
		e.start();
		} catch (Throwable x) {
			CommandPhalanx.info("Engine explodiert");
			throw x;
		}
			
	}
	
	private void start() {
		ParserStart starter = new ParserStart(commandQueue);
		starter.start();
		while (!finished) {
//			CommandPhalanx.info("Erwarte Kdo"); //TODO Test
			Object command = getOrder();
//			if(command == null)
//				System.out.println("null"); //TODO Test
			if(!(command == null)){
				CommandPhalanx.info(command.toString()); //TODO Test
				CommandPhalanx.info(command.getClass().toString());
				if(command.getClass().toString().equals("class java.lang.String")) {
					executeStringCommand((String)command);
				} else if (command.getClass().toString().equals("class [Ljava.lang.String;")) {
					executePosition((String[]) command);
				} else if (command.getClass().toString().equals("class [[Ljava.lang.String;")) {
					executeStringDoubleArrayCommand((String[][]) command);
				}
			}
		}
	}
	
	private void executeStringDoubleArrayCommand(String[][] command) {
		CommandPhalanx.infoString("Double Array Kdo"); //TODO Test
		if (command[0][0].equals("go")){
			if(!searching){
				CommandPhalanx.info("Berechnung startet!");
				searcher = new AlphaBeta(board, board.isSideWhite(), false, 60);
				searcher.start();
				searching = true;
			}
		}
		
	}

	private void executePosition(String[] command) {
		CommandPhalanx.infoString("Position Kdo"); //TODO Test
		board = new Board(command);
	}

	private void executeStringCommand(String command) {
		CommandPhalanx.infoString("Ein String Kdo"); //TODO Test
		CommandPhalanx.info("Empfangenes Kdo: " + command);
		if(command.equals("quit")) {
			finished=true;
			if(searcher != null)
				searcher.interrupt();
			CommandPhalanx.info("Engine Meldet sich ab");
		} else if(command.equals("board")) {
			System.out.println(board.toString());
		} else if(command.equals("stop")) {
			String bestmove;
			if (searching) {
				searcher.interrupt();
				bestmove = searcher.getBestMove();
				CommandPhalanx.info("BM: " + bestmove); //TODO Test
				CommandPhalanx.bestmove(bestmove);
				int start = board.toField(bestmove.substring(0, 2));
				int destination = board.toField(bestmove.substring(2, 4));
				int changedPiece = Board.EMPTY_FIELD;
				if(bestmove.length() > 4) {
					char piece = bestmove.charAt(4);
					if(board.isSideWhite()) {
						switch(piece){
						case 'R': changedPiece = Board.WHITE_ROOK; break;
						case 'N': changedPiece = Board.WHITE_KNIGHT; break;
						case 'B': changedPiece = Board.WHITE_BISHOP; break;
						case 'Q': changedPiece = Board.WHITE_QUEEN; break;
						}
					} else {
						switch(piece){
						case 'R': changedPiece = Board.BLACK_ROOK; break;
						case 'N': changedPiece = Board.BLACK_KNIGHT; break;
						case 'B': changedPiece = Board.BLACK_BISHOP; break;
						case 'Q': changedPiece = Board.BLACK_QUEEN; break;
						}
					}
				}
				CommandPhalanx.info("ZUG!");
				CommandPhalanx.info("Koordinaten:"  + bestmove.substring(0, 2) + " : "
													+ board.toField(bestmove.substring(0, 2)) + " : " 
													+ bestmove.substring(2, 4) + " : "
													+ board.toField(bestmove.substring(2, 4)) + " : " 
													+changedPiece);
				board.move(start, destination, changedPiece);
				searching = false;
			} else {
				CommandPhalanx.info("Engine sucht nicht");
			}
		}
	}
	
	private synchronized Object getOrder() {
		return commandQueue.poll();
	}

	private class ParserStart extends Thread {
		private LinkedList queue;
		
		public ParserStart(LinkedList list) {
			queue = list;
		}
		
		public void run() {
			Kdoparser.start(queue);			
		}
		
	}
}
